import numpy as np
import sympy as sp
import sympy_to_numpy_func
from sympy.tensor.array import derive_by_array


def create_f1():
    """
    Create a function which has singular Hessian at starting point.

    Note: only for verification purpose, not a benchmark.

    :return:  x0, f, g G
    """
    x = [sp.var('x' + str(i)) for i in range(2)]
    x1, x2 = x[0], x[1]
    x0 = np.array([1, -1], dtype=np.float64)
    f = (2.0 * x1 * x2) + (0.5 * x1 ** 2) + ((1.0 / 3.0) * x2 ** 4)
    g = derive_by_array(f, x)
    h = sp.hessian(f, x)
    return sympy_to_numpy_func.create_function(x, x0, f, g, h)


def create_f2():
    """
    Create a function which has singular Hessian at starting point,
    and no zero-curvature descent direction.

    Note: only for verification purpose, not a benchmark.

    :return:
    """
    x = [sp.var('x' + str(i)) for i in range(2)]
    x1, x2 = x[0], x[1]
    x0 = np.array([1, -1], dtype=np.float64)
    f = (2.0 * x1 * x2) + (0.5 * x1 ** 2) + (2.0 * x2 ** 2)
    g = derive_by_array(f, x)
    h = sp.hessian(f, x)
    return sympy_to_numpy_func.create_function(x, x0, f, g, h)
